//
// Created by denglibin on 2019/6/18 0018.
//
/**面向对象实现线程池**/
#include <iostream>
#include <thread>
#include <queue>
#include <mutex>
#include <condition_variable>
#include <vector>
using namespace std;
/**
 * 线程池任务接口
 */
class Task{
public:
    void virtual run() = 0 ;
    virtual ~Task(){};
};

class MyTask : public Task{
private:
    int id;
public:
    MyTask(int id){
        this->id = id;
    }
    void virtual run()override{
        this_thread::sleep_for(chrono::seconds(1));
        cout << " task id:" << id << endl;
    }
    virtual ~MyTask()override{

    }
};
class MyThreadPool{
private:
    bool running;
    int size; //线程池大小
    shared_ptr<vector<shared_ptr<thread>>> worker;
    shared_ptr<mutex> lock; //互斥锁
    shared_ptr<queue<shared_ptr<Task>>> taskQueue; //任务队列
    shared_ptr<condition_variable> condition;
    /**
     * 执行任务
     */
    void executeTask(){
        while (true){
            unique_lock<mutex> unique_lock(*lock, defer_lock);
            unique_lock.lock();
            if(running && taskQueue->empty()){
                //无任务 阻塞
                cout << "blocked," << endl;
                condition->wait(unique_lock);
            }
            //线程停止并且没任务
            if(!running &&  taskQueue->empty()){
                return;
            }
            shared_ptr<Task> task = taskQueue->front();
            taskQueue->pop();
            unique_lock.unlock();
            task->run();

        }
    }
    /**
     * 初始化
     */
    void init(){
        lock = make_shared<mutex>(); //创建锁
        taskQueue = make_shared<queue<shared_ptr<Task>>>(); //创建队列
        worker = make_shared<vector<shared_ptr<thread>>>();//创建线程集合
        condition = make_shared<condition_variable>();
        //创建线程
        for(int i = 0; i < size; i++){
            shared_ptr<thread> t = make_shared<thread>(&MyThreadPool::executeTask, this);
            worker->emplace_back(t);
        }
    }
public:
    MyThreadPool(int size){
        this->size = size;
        running = true;
        init();
    }
    /**
     * 执行任务
     */
    void execute(shared_ptr<Task> task){
        taskQueue->push(task);
        condition->notify_one();
    }

    ~MyThreadPool(){
        running = false;
        condition->notify_all();
        for(auto var : *worker){
            var->join();
        }
    }
};

int main56(){

    shared_ptr<MyThreadPool> threadPool = make_shared<MyThreadPool>(10);
    this_thread::sleep_for(std::chrono::seconds(2));
    for(int i  = 0; i < 10; i++){
        threadPool->execute(make_shared<MyTask>(i+1));
    }
    return 0;
}